home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
program
/
cgazv4n3.zip
/
COMPRESS.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-02-07
|
14KB
|
372 lines
PAGE 60,132
; ------------------- COMPRESS.ASM --- LISTING 1 -----------------
; Contains the 2 functions, Pack3 and UnPack3.
;
; Assembler: Microsoft Assembler (MASM) or Turbo Assembler (TASM)
; Memory model: any
;
; To assemble : MASM compress /ML /dMSIZE=?;
; or TASM compress /ML /dTASM /dMSIZE=?;
;
; where MSIZE = 1 Small Memory Model code<64k data<64k
; = 2 Medium Memory Model code>64k data<64k
; = 3 Compact Memory Model code<64k data>64k
; = 4 Large Memory Model code>64k data>64k
;
; Author : Bob Zigon
; Date : June 9, 1988
; -------------------------------------------------------------------
DOSSEG
IFNDEF MSIZE
%OUT ***
%OUT *** ERROR : Must specify MSIZE param for Memory Model Selection
%OUT ***
ELSE
IF MSIZE LT 1 OR MSIZE GT 4
%OUT ***
%OUT *** ERROR : MSIZE Range 1 - 4
%OUT ***
ENDIF
IF MSIZE EQ 1
IFNDEF TASM
.model small,c
ELSE
.model small
ENDIF
%OUT *** Memory Model : SMALL
ENDIF
IF MSIZE EQ 2
IFNDEF TASM
.model medium,c
ELSE
.model medium
ENDIF
%OUT *** Memory Model : MEDIUM
ENDIF
IF MSIZE EQ 3
IFNDEF TASM
.model compact,c
ELSE
.model compact
ENDIF
%OUT *** Memory Model : COMPACT
ENDIF
IF MSIZE EQ 4
IFNDEF TASM
.model large,c
ELSE
.model large
ENDIF
%OUT *** Memory Model : LARGE
ENDIF
ENDIF
.data
include COMPRESS.TBL ; see example
.code
; -------------------------------------------------------------------
; PACK3 -- this routine will compress a string of characters into exactly
; 2/3 the space according to the translation tables built by
; BUILD.C.
;
; The algorithm is based on the following polynomial.
;
; P(C1, C2, C3) = C3*40**2 + C2*40**1 + C1*40**0
;
;
; C Prototype :
;
; short int Pack3(char *InpBuf, short int NumChar, char *OutBuf)
;
;
; Input : InpBuf -- Ptr to the Input Buffer.
; NumChar -- Number of characters to Pack (Must be > 0).
; OutBuf -- Ptr to Output Buffer.
;
; Return : Number of words in the packed string.
; -------------------------------------------------------------------
IFNDEF TASM ; MASM prologue
Pack3 PROC USES SI DI, InpBuf:PTR, NumChar:WORD, OutBuf:PTR
LOCAL NumXlate:WORD
ELSE ; TASM prologue
public _Pack3
_Pack3 PROC
ARG InpBuf:PTR,NumChar:WORD,OutBuf:PTR
LOCAL NumXlate:WORD=AutoSize
push bp
mov bp,sp
sub sp,AutoSize ; Allocate some local variables
push si
push di ; Save in case Register Variables = ON
ENDIF
xor ax,ax
mov NumXlate,ax ; Zero out NumXlate
IF MSIZE EQ 3 OR MSIZE EQ 4 ; 32 bit pointers
les si,InpBuf
mov cx,es ; Save Source String segment
p10: mov es,cx ; ES is segment of Source String
mov al,es:[si] ; Get a character from the source string
inc si ; Inc offset portion of pointer
shl ax,1 ; Times 2 for word addressing
mov bx,ax
lea bx,Xlate0[bx] ; BX points to the term to sum into DX
mov dx, [bx] ; DX will accumulate the polynomial
dec WORD PTR NumChar ; 1 less character to consider
jz p100 ; Exit when no more characters to translate
mov al,es:[si] ; Get a character from the source string
inc si
shl ax,1 ; Times 2 for word addressing
mov bx,ax
lea bx,Xlate1[bx] ; BX points to the term to sum into DX
add dx, [bx] ; Add in the next term
dec WORD PTR NumChar ; 1 less character to consider
jz p100 ; Exit when no more characters to translate
mov al,es:[si] ; Get a character from the source string
inc si
shl ax,1 ; Times 2 for word addressing
mov bx,ax
lea bx,Xlate2[bx] ; BX points to the term to sum into DX
add dx, [bx] ; Add in the last term
les di,OutBuf
mov es:[di],dx ; Save the result to the Output buffer
inc WORD PTR [OutBuf] ; Increment twice
inc WORD PTR [OutBuf]
inc WORD PTR NumXlate
dec WORD PTR NumChar ; 1 less character to consider
jz p110 ; Exit when no more characters to translate
jmp short p10
p100: les di,OutBuf
mov es:[di],dx
inc WORD PTR NumXlate
p110: mov ax,NumXlate ; Return the Number of Words in dest
ELSE
mov si,InpBuf ; SI will point to the input buffer
mov di,OutBuf ; DI will point to the output buffer
cld
p10: lodsb ; Get a character from the source string
shl ax,1 ; Times 2 for word addressing
mov bx,ax
lea bx,Xlate0[bx] ; BX points to the term to sum into DX
mov dx, [bx] ; DX will accumulate the polynomial
dec WORD PTR NumChar ; 1 less character to consider
jz p100 ; Exit when no more characters to translate
lodsb ; Get a character from the source string
shl ax,1 ; Times 2 for word addressing
mov bx,ax
lea bx,Xlate1[bx] ; BX points to the term to sum into DX
add dx, [bx] ; Add in the next term
dec WORD PTR NumChar ; 1 less character to consider
jz p100 ; Exit when no more characters to translate
lodsb ; Get a character from the source string
shl ax,1 ; Times 2 for word addressing
mov bx,ax
lea bx,Xlate2[bx] ; BX points to the term to sum into DX
add dx, [bx] ; Add in the last term
mov [di],dx ; Save the result to the Output buffer
inc di
inc di ; Inc offset twice for word addressing
inc WORD PTR NumXlate
dec WORD PTR NumChar ; 1 less character to consider
jz p110 ; Exit when no more characters to translate
jmp short p10
p100: mov [di],dx
inc WORD PTR NumXlate
p110: mov ax,NumXlate ; Return the Number of Words in dest
ENDIF
IFNDEF TASM
ret ; MASM does cleanup automatically
Pack3 endp
ELSE ; TASM cleanup
pop di
pop si
mov sp,bp ; Deallocate the local variables
pop bp ; Reset BP
ret
_Pack3 endp
ENDIF
; -------------------------------------------------------------------
; UNPACK3 -- this routine will unpack the string of characters that
; were previously packed with PACK3. The length of the
; unpacked string will be a multiple of 3. The unpacked
; string will also be NULL terminated.
;
; C Prototype :
;
; short int UnPack3(char *InpBuf, short int NumWord, char *OutBuf)
;
;
; Input : InpBuf -- Ptr to the Input Buffer.
; NumWord -- Number of words to UnPack (Must be > 0).
; OutBuf -- Ptr to Output Buffer.
;
; Return : Number of characters in the unpacked string.
; -------------------------------------------------------------------
IFNDEF TASM ; MASM prologue
UnPack3 PROC USES DI SI, InpBuf:PTR,NumWord:WORD,OutBuf:PTR
LOCAL NumConvert:WORD
ELSE ; TASM prologue
public _UnPack3
_UnPack3 proc
arg InpBuf:PTR,NumWord:WORD,OutBuf:PTR
local NumConvert:word=AutoSize
push bp
mov bp,sp
sub sp,AutoSize ; Allocate some local variables
push si
push di ; Save in case Register Variables = ON
ENDIF
xor ax,ax
mov dx,ax
mov NumConvert,ax
mov cx,40 ; Divisor for extracting character
IF MSIZE EQ 3 OR MSIZE EQ 4 ; 32 bit pointers
up10: les di,InpBuf
mov ax,es:[di]
inc WORD PTR [InpBuf]
inc WORD PTR [InpBuf]
;
; The following 3 blocks of code are identical. You could very easily
; loop over the first block 3 times and achieve the same effect. I however
; feel that speed is more important than memory utilization. As a result,
; I prefer to 'unwrap' the loop 3 times and produce the inline code, than
; suffer the penalties associated with flushing the prefetch queue when
; the necessary jump at the bottom of the loop is executed.
;
div cx ; DX will get the remainder
shl dx,1 ; *2 for word addressing into ToAscii Table
mov bx,dx
xor dx,dx ; Zero out DX for the next division
lea bx,ToAscii[bx] ; BX points into the table
mov bx,[bx] ; BX now has the ascii value
les di,OutBuf ; Load ES:DI once
mov es:[di],bl ; Store the character to the output buffer
inc di ; Now just inc DI
inc WORD PTR NumConvert ; We converted the 1st character
div cx ; DX will get the remainder
shl dx,1 ; *2 for word addressing into ToAscii Table
mov bx,dx
xor dx,dx ; Zero out DX for the next division
lea bx,ToAscii[bx] ; BX points into the table
mov bx,[bx] ; BX now has the ascii value
mov es:[di],bl ; Store the character to the output buffer
inc di
inc WORD PTR NumConvert ; We converted the 2nd character
div cx ; DX will get the remainder
shl dx,1 ; *2 for word addressing into ToAscii Table
mov bx,dx
xor dx,dx ; Zero out DX for the next division
lea bx,ToAscii[bx] ; BX points into the table
mov bx,[bx] ; BX now has the ascii value
mov es:[di],bl ; Store the character to the output buffer
inc di
mov word ptr [OutBuf],di ; Update the pointer offset
inc WORD PTR NumConvert ; We converted the 3rd character
dec WORD PTR NumWord ; 1 less word to consider
jnz up10
xor al,al
mov es:[di],al ; Null terminate the buffer
mov ax,NumConvert
ELSE
mov si,InpBuf ; SI will point to the input buffer
mov di,OutBuf ; DI will point to the output buffer
cld
up10: lodsw ; AX <-- [SI++]
;
; The following 3 blocks of code are identical. You could very easily
; loop over the first block 3 times and achieve the same effect. I however
; feel that speed is more important than memory utilization. As a result,
; I prefer to 'unwrap' the loop 3 times and produce the inline code, than
; suffer the penalties associated with flushing the prefetch queue when
; the necessary jump at the bottom of the loop is executed.
;
div cx ; DX will get the remainder
shl dx,1 ; *2 for word addressing into ToAscii Table
mov bx,dx
xor dx,dx ; Zero out DX for the next division
lea bx,ToAscii[bx] ; BX points into the table
mov bx,[bx] ; BX now has the ascii value
mov [di],bl ; Store the character to the output buffer
inc di
inc WORD PTR NumConvert ; We converted the 1st character
div cx ; DX will get the remainder
shl dx,1 ; *2 for word addressing into ToAscii Table
mov bx,dx
xor dx,dx ; Zero out DX for the next division
lea bx,ToAscii[bx] ; BX points into the table
mov bx,[bx] ; BX now has the ascii value
mov [di],bl ; Store the character to the output buffer
inc di
inc WORD PTR NumConvert ; We converted the 2nd character
div cx ; DX will get the remainder
shl dx,1 ; *2 for word addressing into ToAscii Table
mov bx,dx
xor dx,dx ; Zero out DX for the next division
lea bx,ToAscii[bx] ; BX points into the table
mov bx,[bx] ; BX now has the ascii value
mov [di],bl ; Store the character to the output buffer
inc di
inc WORD PTR NumConvert ; We converted the 3rd character
dec WORD PTR NumWord ; 1 less word to consider
jnz up10
xor al,al
mov [di],al ; Null terminate the buffer
mov ax,NumConvert
ENDIF
IFNDEF TASM ; Cleanup for MASM
ret
UnPack3 endp
ELSE ; Clean up for TASM
pop di
pop si
mov sp,bp ; Deallocate the local variables
pop bp ; Reset BP
_UnPack3 endp
ENDIF
end